#include "network.h"
#include <QNetworkDatagram>
#include <QDebug>

network::network(QObject *parent)
    : QObject{parent}
{
    // 定义文本编码
    tc = QTextCodec::codecForName("UTF-8");
    // 实例化TCP服务端
    tcpServer = new QTcpServer();
    connect(tcpServer, &QTcpServer::newConnection, this, &network::TCPServer_newConnect);
    // 实例化TCP客户端
    tcpClient = new QTcpSocket();
    connect(tcpClient, &QTcpSocket::connected, this, &network::TCPClient_newConnect);
    connect(tcpClient, &QTcpSocket::disconnected, this, &network::TCPClient_disconnect);
    connect(tcpClient, &QTcpSocket::readyRead, this, &network::TCPClient_readData);
    // 实例化UDP
    udpSocket = new QUdpSocket();
    connect(udpSocket, &QUdpSocket::readyRead, this, &network::UDP_readData);
}

bool network::TCPServer_open(QString ownIp, unsigned short ownPort)
{
    bool result = true;
    if(ownIp.length() < 10)
    {
        // 监听本地ip和port以监测有无接收数据
        result = tcpServer->listen(QHostAddress::Any, ownPort);
    }
    else
    {
        result = tcpServer->listen(QHostAddress(ownIp), ownPort);
    }
    return result;
//    if(!result)
//    {
//        qDebug() << "(TCP Server) listen fail";
//        return false;
//    }
//    qDebug() << "(TCP Server) listen success";
//    return true;
}

void network::TCPServer_close()
{
    tcpServer->close();
}

void network::TCPServer_newConnect()
{
    QTcpSocket *newTcpClient = tcpServer->nextPendingConnection(); // 新的客户端发起的连接
    //QHostAddress newClientIp = newTcpClient->peerAddress(); // 新的客户端的IP
    //quint16 newClientPort = newTcpClient->peerPort(); // 新的客户端的端口
    // 是否已存在连接列表中
    if(clientList.contains(newTcpClient))
    {
        //qDebug() << QString("(TCP Server) already exist IP:%1 PORT:%2").arg(newClientIp.toString()).arg(newClientPort);
    }
    else
    {
        clientList.append(newTcpClient); // 记录新的客户端
        // 连接信号
        connect(newTcpClient, &QTcpSocket::disconnected, this, &network::TCPServer_disconnect); // 断开连接的信号与槽
        connect(newTcpClient, &QTcpSocket::readyRead, this, &network::TCPServer_readData); // 数据接收的信号与槽 readyRead()是QIODevice下的信号
        //qDebug() << QString("(TCP Server) new connect IP:%1 PORT:%2").arg(newClientIp.toString()).arg(newClientPort);
    }
}

void network::TCPServer_disconnect()
{
    QTcpSocket *newTcpClient = static_cast<QTcpSocket *>(QObject::sender());
    clientList.removeOne(newTcpClient); // 移除断开连接的客户端
    // 断开信号
    disconnect(newTcpClient, &QTcpSocket::disconnected, this, &network::TCPServer_disconnect); // 断开连接的信号与槽
    disconnect(newTcpClient, SIGNAL(readyRead()), this, SLOT(TCPServer_readData())); // 数据接收的信号与槽
    //qDebug() << "(TCP Server) disconnect";
}

void network::TCPServer_readData()
{
    QTcpSocket *newTcpClient = static_cast<QTcpSocket *>(QObject::sender());
    this->TCPServer_dataBuf = newTcpClient->readAll();
    this->TCPServer_rxByte += tc->toUnicode(this->TCPServer_dataBuf).length();
    emit this->tcpServer_readSuccess(this->TCPServer_rxByte);
    //qDebug() << "(TCP Server) rec data:" + tc->toUnicode(TCPServer_dataBuf);
}

void network::TCPServer_sendData(QByteArray sendData)
{
    int byteTemp = 0;
    foreach(QTcpSocket *socket, clientList)
    {
        byteTemp = socket->write(sendData);
    }
    // 发送失败返回-1
    if(byteTemp != -1)
    {
        this->TCPServer_txByte += byteTemp;
        emit this->tcpServer_sendSuccess(this->TCPServer_txByte);
    }
}

bool network::TCPClient_open(QString remoteIp, unsigned short remotePort)
{
    QHostAddress serverIp;
    // IP错误则返回false
    if(!serverIp.setAddress(remoteIp))
    {
        //qDebug() << "(TCP Client) remoteIp error";
        return false;
    }
    // 防止TCP Client已打开
    if(tcpClient->isOpen())
    {
        tcpClient->close();
    }
    tcpClient->connectToHost(serverIp, remotePort);
    // 是否连接成功
    if(!tcpClient->waitForConnected(500))
    {
        //qDebug() << "(TCP Client) tcp client connect fail";
        return false;
    }
    return true;
}

void network::TCPClient_close()
{
    tcpClient->close();
}

void network::TCPClient_newConnect()
{
    //qDebug() << "(TCP Client) new connect";
}

void network::TCPClient_disconnect()
{
    if(tcpClient->isOpen())
    {
        tcpClient->close();
    }
    //qDebug() << "(TCP Client) disconnect";
}

void network::TCPClient_readData()
{
    this->TCPClient_dataBuf = tcpClient->readAll();
    this->TCPClient_rxByte += tc->toUnicode(this->TCPClient_dataBuf).length();
    emit this->tcpClient_readSuccess(this->TCPClient_rxByte);
    //qDebug() << "(TCP Client) rec data:" + tc->toUnicode(TCPClient_dataBuf);
}

void network::TCPClient_sendData(QByteArray sendData)
{
    int byteTemp = 0;
    byteTemp = tcpClient->write(sendData);
    // 发送失败返回-1
    if(byteTemp != -1)
    {
        this->TCPClient_txByte += byteTemp;
        emit this->tcpClient_sendSuccess(this->TCPClient_txByte);
    }
    //qDebug() << "(TCP Client) send byte:" << byteTemp;
}

bool network::UDP_open(QString ownIp, unsigned short ownPort, QString remoteIp, unsigned short remotePort)
{
    bool result = true;
    if(ownIp.length() < 10)
    {
        // 绑定本地ip和port以监测有无接收数据
        result = udpSocket->bind(QHostAddress::Any, ownPort);
    }
    else
    {
        result = udpSocket->bind(QHostAddress(ownIp), ownPort);
    }
    this->UDP_remoteIp = QHostAddress(remoteIp);
    this->UDP_remotePort = remotePort;
    return result;
//    if(!result)
//    {
//        qDebug() << "UDP open fail";
//        return false;
//    }
//    qDebug() << "UDP open success";
//    return true;
}

void network::UDP_close()
{
    udpSocket->close();
}

void network::UDP_readData()
{
    while(udpSocket->hasPendingDatagrams())
    {
         QNetworkDatagram datagram = udpSocket->receiveDatagram();
         this->UDP_dataBuf = datagram.data();
         this->UDP_rxByte += tc->toUnicode(this->UDP_dataBuf).length();
         emit this->udp_readSuccess(this->UDP_rxByte);
         //qDebug() << datagram.data();
    }
}

void network::UDP_sendData(QByteArray sendData)
{
    int byteTemp = 0;
    byteTemp = udpSocket->writeDatagram(sendData, this->UDP_remoteIp, this->UDP_remotePort);
    // 发送失败返回-1
    if(byteTemp != -1)
    {
        this->UDP_txByte += byteTemp;
        emit this->udp_sendSuccess(this->UDP_txByte);
    }
}
